"use strict";

// ##################
// # Create simulator #
// ##################

// legend:
// ni == simulator.nodes[i]
// pi == simulator.elements[i]

//        0     2        3      4     5     6      7    8     9      10
//  3         n3                 n4                 n8
//                            
//  2         n2               n5                 n9
//               \               \                  \
//  1             p1               p2       n7       p4
//                  \               \    / p3         \
//  0     n0 - p0 - n1                n6               n10-p5-n11-p6-n12

// #########
// # Nodes #
// #########
simulator.nodes.push(new Simulatable.Node($V([ 0.1 , 0.1]))); // 0
simulator.nodes.push(new Simulatable.Node($V([ 3.1 , 0.1]))); // 1
simulator.nodes.push(new Simulatable.Node($V([ 2.1 , 1.1]))); // 2
simulator.nodes.push(new Simulatable.Node($V([ 0.1 , 3.1]))); // 3

simulator.nodes.push(new Simulatable.Node($V([ 4.11, 3.1]))); // 4
simulator.nodes.push(new Simulatable.Node($V([ 4.1 , 2.1]))); // 5
simulator.nodes.push(new Simulatable.Node($V([ 5.1 , 0.1]))); // 6
simulator.nodes.push(new Simulatable.Node($V([ 6.1 , 1.1]))); // 7

simulator.nodes.push(new Simulatable.Node($V([ 7.11, 3.1]))); // 8
simulator.nodes.push(new Simulatable.Node($V([ 7.1 , 2.1]))); // 9
simulator.nodes.push(new Simulatable.Node($V([ 8.1 , 0.1]))); // 10
simulator.nodes.push(new Simulatable.Node($V([ 9.1 , 0.1]))); // 11
simulator.nodes.push(new Simulatable.Node($V([10.1 , 0.1]))); // 12

// ########
// # Rods #
// ########
var length = 1.0;
var radius = 0.1;
var youngsModulus_weak  =  500;
var youngsModulus_stiff = 5000;
var density = 10;
var internalFriction_weak  = 3;
var internalFriction_stiff = 50;

simulator.elements.push(new Simulatable.Rod(length, radius, youngsModulus_weak , density, internalFriction_weak )); // 0
simulator.elements.push(new Simulatable.Rod(length, radius, youngsModulus_weak , density, internalFriction_weak )); // 1
simulator.elements.push(new Simulatable.Rod(length, radius, youngsModulus_weak , density, internalFriction_weak )); // 2
simulator.elements.push(new Simulatable.Rod(length, radius, youngsModulus_weak , density, internalFriction_weak )); // 3
simulator.elements.push(new Simulatable.Rod(length, radius, youngsModulus_stiff, density, internalFriction_stiff)); // 4
simulator.elements.push(new Simulatable.Rod(length, radius, youngsModulus_stiff, density, internalFriction_stiff)); // 5
simulator.elements.push(new Simulatable.Rod(length, radius, youngsModulus_stiff, density, internalFriction_stiff)); // 6

// ####################
// # Standalone Ports #
// ####################
var gravity = new Simulatable.Gravity($V([0.0, -9.8]));
var someMassPoint = new Simulatable.MassPoint(1.0);
var heavyPoint = new Simulatable.MassPoint(Number.POSITIVE_INFINITY);

// ###################################
// # Objects Causing External Forces #
// ###################################
var ball0 = new Simulatable.Ball(0.5);
var ball1 = new Simulatable.Ball(0.5);
var ball2 = new Simulatable.Ball(0.5);

// ##########################
// # Connect Rods and Nodes #
// ##########################

// There exist two possibilities to define fixed nodes
// Possibility 1
//   Call Port.setNode(node) and Node.addPort(port) and add an infinitely heavy mass point to the node
// Possibility 2 (works only in absence of external forces)
//   Call only Port.setNode(node) and add a mass point with an arbitrary, but nonzero mass to the node (to avoid division by zero)

// does not use bidirectional connection because node0 is fixed

// #############
// # Nodes 0-3 #
// #############
simulator.elements[0].ports[0].setNode(simulator.nodes[0]);
//simulator.connectNodeAndPort(simulator.nodes[0], simulator.elements[0].ports[0]);
simulator.connectNodeAndPort(simulator.nodes[1], simulator.elements[0].ports[1]);
simulator.connectNodeAndPort(simulator.nodes[1], simulator.elements[1].ports[0]);
simulator.connectNodeAndPort(simulator.nodes[2], simulator.elements[1].ports[1]);

simulator.nodes[0].addPort(someMassPoint);
simulator.nodes[1].addPort(gravity);
simulator.nodes[2].addPort(gravity);
simulator.nodes[3].addPort(gravity);
simulator.nodes[3].addPort(someMassPoint);
simulator.connectNodeAndIndiePort(simulator.nodes[3], ball0);

// #############
// # Nodes 4-7 #
// #############

simulator.connectNodeAndPort(simulator.nodes[5], simulator.elements[2].ports[0]);
simulator.connectNodeAndPort(simulator.nodes[6], simulator.elements[2].ports[1]);
simulator.connectNodeAndPort(simulator.nodes[6], simulator.elements[3].ports[0]);
simulator.connectNodeAndPort(simulator.nodes[7], simulator.elements[3].ports[1]);

simulator.nodes[4].addPort(someMassPoint);
simulator.nodes[4].addPort(gravity);
simulator.connectNodeAndIndiePort(simulator.nodes[4], ball1);
simulator.nodes[5].addPort(heavyPoint);
simulator.nodes[6].addPort(gravity);
simulator.nodes[7].addPort(heavyPoint);

// ##############
// # Nodes 8-12 #
// ##############

simulator.connectNodeAndPort(simulator.nodes[ 9], simulator.elements[4].ports[0]);
simulator.connectNodeAndPort(simulator.nodes[10], simulator.elements[4].ports[1]);
simulator.connectNodeAndPort(simulator.nodes[10], simulator.elements[5].ports[0]);
simulator.connectNodeAndPort(simulator.nodes[11], simulator.elements[5].ports[1]);
simulator.connectNodeAndPort(simulator.nodes[11], simulator.elements[6].ports[0]);
simulator.connectNodeAndPort(simulator.nodes[12], simulator.elements[6].ports[1]);

simulator.nodes[ 8].addPort(someMassPoint);
simulator.nodes[ 8].addPort(gravity);
simulator.connectNodeAndIndiePort(simulator.nodes[8], ball2);
simulator.nodes[ 9].addPort(heavyPoint);
simulator.nodes[10].addPort(gravity);
simulator.nodes[11].addPort(gravity);
simulator.nodes[12].addPort(heavyPoint);

// #########################
// # Perform One Time Step #
// #########################

if (false) {
	var fps = 40.0;
	var slowmotionFactor = 1.0;
	var timeStep = 1.0/fps/slowmotionFactor;
	var damping = 0.7;

	// simulator.printNodes(simulator.nodes);
	// simulator.printElements(simulator.elements);

	simulator.setZeroVelocity(simulator.nodes);
	simulator.advanceTime(timeStep, damping);

	//simulator.printNodes(simulator.nodes);
	//simulator.printElements(simulator.elements);
}

//document.write($V([1,2]).add($V([6,4])).elements);

// ###################
// # Create Renderer #
// ###################
renderer.objects.push(new Renderables.Rod(simulator.elements[0]));
renderer.objects.push(new Renderables.Rod(simulator.elements[1]));
renderer.objects.push(new Renderables.Rod(simulator.elements[2]));
renderer.objects.push(new Renderables.Rod(simulator.elements[3]));
renderer.objects.push(new Renderables.Rod(simulator.elements[4]));
renderer.objects.push(new Renderables.Rod(simulator.elements[5]));
renderer.objects.push(new Renderables.Rod(simulator.elements[6]));

renderer.objects.push(new Renderables.Ball(ball0));
renderer.objects.push(new Renderables.Ball(ball1));
renderer.objects.push(new Renderables.Ball(ball2));

// add nodes afterwards to overdraw balls
renderer.objects.push(new Renderables.Node(simulator.nodes[ 0]));
renderer.objects.push(new Renderables.Node(simulator.nodes[ 1]));
renderer.objects.push(new Renderables.Node(simulator.nodes[ 2]));
renderer.objects.push(new Renderables.Node(simulator.nodes[ 3]));
renderer.objects.push(new Renderables.Node(simulator.nodes[ 4]));
renderer.objects.push(new Renderables.Node(simulator.nodes[ 5]));
renderer.objects.push(new Renderables.Node(simulator.nodes[ 6]));
renderer.objects.push(new Renderables.Node(simulator.nodes[ 7]));
renderer.objects.push(new Renderables.Node(simulator.nodes[ 8]));
renderer.objects.push(new Renderables.Node(simulator.nodes[ 9]));
renderer.objects.push(new Renderables.Node(simulator.nodes[10]));
renderer.objects.push(new Renderables.Node(simulator.nodes[11]));
renderer.objects.push(new Renderables.Node(simulator.nodes[12]));

// ###################
// # Simulation Loop #
// ###################

/*
var lastTime = null;

var cnt = 0;
var hndInterval = setInterval( function() {
	simulator.advanceTime(timeStep, damping);
	renderer.render(renderer.objects);
	
	var curTime = new Date().getTime();
	if (lastTime) {
		renderer.getContext().fillText(Math.round(1000/(curTime - lastTime)) + " fps", 0, 20);
	}
	lastTime = curTime;

	if( cnt++ > 1000 ) {
		clearInterval( hndInterval) ;
	}
}, 1000.0/fps );
*/

//simulator.printNodes(simulator.nodes);
//simulator.printElements(simulator.elements);
